package demoMod.nanaki.patches.events.beyond;

import basemod.ReflectionHacks;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.evacipated.cardcrawl.modthespire.Loader;
import com.evacipated.cardcrawl.modthespire.lib.SpirePatch;
import com.evacipated.cardcrawl.modthespire.lib.SpireReturn;
import com.megacrit.cardcrawl.actions.AbstractGameAction;
import com.megacrit.cardcrawl.cards.curses.AscendersBane;
import com.megacrit.cardcrawl.characters.AbstractPlayer;
import com.megacrit.cardcrawl.core.CardCrawlGame;
import com.megacrit.cardcrawl.core.Settings;
import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
import com.megacrit.cardcrawl.dungeons.Exordium;
import com.megacrit.cardcrawl.events.AbstractImageEvent;
import com.megacrit.cardcrawl.events.GenericEventDialog;
import com.megacrit.cardcrawl.events.beyond.SecretPortal;
import com.megacrit.cardcrawl.helpers.MathHelper;
import com.megacrit.cardcrawl.helpers.controller.CInputActionSet;
import com.megacrit.cardcrawl.helpers.input.InputHelper;
import com.megacrit.cardcrawl.localization.EventStrings;
import com.megacrit.cardcrawl.localization.UIStrings;
import com.megacrit.cardcrawl.relics.AbstractRelic;
import com.megacrit.cardcrawl.rooms.AbstractRoom;
import com.megacrit.cardcrawl.ui.buttons.DynamicBanner;
import com.megacrit.cardcrawl.ui.buttons.UnlockConfirmButton;
import com.megacrit.cardcrawl.unlock.AbstractUnlock;
import com.megacrit.cardcrawl.unlock.UnlockTracker;
import demoMod.nanaki.NanakiMod;
import demoMod.nanaki.characters.NanakiCharacter;
import demoMod.nanaki.patches.CharacterSelectScreenPatch;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;

public class SecretPortalPatch {
    public static final String ID = NanakiMod.makeID("SecretPortal");
    private static final EventStrings eventStrings;
    public static final String NAME;
    public static final String[] DESCRIPTIONS;
    public static final String[] OPTIONS;

    @SpirePatch(
            clz = SecretPortal.class,
            method = SpirePatch.CONSTRUCTOR
    )
    public static class PatchConstructor {
        public static void Postfix(SecretPortal event) {
            AbstractPlayer p = AbstractDungeon.player;
            if (p instanceof NanakiCharacter) {
                if (!p.relics.isEmpty()) {
                    AbstractRelic relicToLose = p.relics.get(p.relics.size() - 1);
                    String displayName = relicToLose.name.replaceAll(" ", " #r");
                    event.imageEventText.setDialogOption(String.format(OPTIONS[2], displayName));
                } else {
                    event.imageEventText.setDialogOption(OPTIONS[3], true);
                }
            }
        }
    }

    @SpirePatch(
            clz = SecretPortal.class,
            method = "buttonEffect"
    )
    public static class PatchButtonEffect {
        private static boolean reversedPortal = false;
        private static final ArrayList<AbstractUnlock> unlockBundle = new ArrayList<>();
        private static final UIStrings uiStrings = CardCrawlGame.languagePack.getUIString(NanakiMod.makeID("NewSkin"));

        public static SpireReturn<Void> Prefix(SecretPortal event, int buttonPressed) {
            if (AbstractDungeon.player instanceof NanakiCharacter) {
                try {
                    Enum screen = ReflectionHacks.getPrivate(event, SecretPortal.class, "screen");
                    if ("INTRO".equals(screen.name())) {
                        reversedPortal = false;
                        if (buttonPressed == 2) {
                            AbstractPlayer p = AbstractDungeon.player;
                            if (!p.relics.isEmpty()) {
                                AbstractRelic relicToLose = p.relics.get(p.relics.size() - 1);
                                p.loseRelic(relicToLose.relicId);
                            }
                            event.imageEventText.updateBodyText(DESCRIPTIONS[3]);
                            ReflectionHacks.setPrivate(event, SecretPortal.class, "screen", Enum.valueOf((Class<Enum>) Class.forName("com.megacrit.cardcrawl.events.beyond.SecretPortal$CurScreen"), "ACCEPT"));
                            AbstractImageEvent.logMetric("SecretPortal", "Reversed Portal");
                            event.imageEventText.updateDialogOption(0, OPTIONS[1]);
                            CardCrawlGame.screenShake.mildRumble(5.0F);
                            CardCrawlGame.sound.play("ATTACK_MAGIC_SLOW_2");
                            reversedPortal = true;
                            event.imageEventText.clearRemainingOptions();
                            if (!NanakiMod.isReskinUnlocked) {
                                NanakiMod.isReskinUnlocked = true;
                                NanakiMod.reskinSaveData.setBool("isReskinUnlocked", true);
                                try {
                                    NanakiMod.reskinSaveData.save();
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                }
                                unlockBundle.clear();
                                AbstractUnlock reskinUnlock = new AbstractUnlock() {
                                    @Override
                                    public void render(SpriteBatch sb) {
                                        this.player.render(sb);
                                    }
                                };
                                reskinUnlock.type = AbstractUnlock.UnlockType.CHARACTER;

                                int tmp = CharacterSelectScreenPatch.reskinIndex;
                                CharacterSelectScreenPatch.reskinIndex = 1; //解锁游戏杀手皮肤
                                reskinUnlock.player = new NanakiCharacter("Nanaki");
                                CharacterSelectScreenPatch.reskinIndex = tmp;
                                reskinUnlock.player.drawX = (float)Settings.WIDTH / 2.0F - 20.0F * Settings.scale;
                                reskinUnlock.player.drawY = (float)Settings.HEIGHT / 2.0F - 118.0F * Settings.scale;
                                unlockBundle.add(reskinUnlock);
                                AbstractDungeon.previousScreen = AbstractDungeon.CurrentScreen.NONE;
                                AbstractDungeon.screen = AbstractDungeon.CurrentScreen.NEOW_UNLOCK;
                                AbstractDungeon.gUnlockScreen.button = new UnlockConfirmButton() {
                                    private <T> T getFieldValue(String fieldName) {
                                        return ReflectionHacks.getPrivate(this, UnlockConfirmButton.class, fieldName);
                                    }

                                    @Override
                                    public void update() {
                                        try {
                                            ReflectionHacks.getCachedMethod(UnlockConfirmButton.class, "animateIn").invoke(this);
                                        } catch (IllegalAccessException | InvocationTargetException e) {
                                            throw new RuntimeException(e);
                                        }

                                        if (AbstractDungeon.getMonsters() != null) {
                                            AbstractDungeon.getMonsters().update();
                                        }

                                        if (!(boolean) getFieldValue("done") && (float) getFieldValue("animTimer") < 0.2F) {
                                            this.hb.update();
                                        }

                                        if (this.hb.hovered && !(boolean) getFieldValue("done")) {
                                            ((Color) getFieldValue("hoverColor")).a = 0.33F;
                                        } else {
                                            ((Color) getFieldValue("hoverColor")).a = MathHelper.fadeLerpSnap(((Color) getFieldValue("hoverColor")).a, 0.0F);
                                        }

                                        if (this.hb.justHovered) {
                                            CardCrawlGame.sound.play("UI_HOVER");
                                        }

                                        if (this.hb.hovered && InputHelper.justClickedLeft) {
                                            this.hb.clickStarted = true;
                                            CardCrawlGame.sound.play("UI_CLICK_1");
                                        }

                                        if (this.hb.clicked || CInputActionSet.select.isJustPressed()) {
                                            CInputActionSet.select.unpress();
                                            this.hb.clicked = false;
                                            this.hb.hovered = false;
                                            if (AbstractDungeon.unlockScreen.unlock != null) {
                                                UnlockTracker.hardUnlock(AbstractDungeon.unlockScreen.unlock.key);
                                                CardCrawlGame.sound.stop("UNLOCK_SCREEN", AbstractDungeon.unlockScreen.id);
                                            } else if (AbstractDungeon.unlocks != null) {
                                                for (AbstractUnlock u : AbstractDungeon.unlocks) {
                                                    UnlockTracker.hardUnlock(u.key);
                                                }
                                            }

                                            InputHelper.justClickedLeft = false;
                                            this.hide();
                                            AbstractDungeon.gUnlockScreen.button = new UnlockConfirmButton();
                                            reskinUnlock.player.dispose();

                                            AbstractDungeon.closeCurrentScreen();
                                        }

                                        ((Color) getFieldValue("textColor")).a = MathHelper.fadeLerpSnap(((Color) getFieldValue("textColor")).a, getFieldValue("target_a"));
                                        ((Color) getFieldValue("btnColor")).a = ((Color) getFieldValue("textColor")).a;
                                    }
                                };
                                NanakiMod.addToBot(new AbstractGameAction() {
                                    @Override
                                    public void update() {
                                        AbstractDungeon.getCurrRoom().phase = AbstractRoom.RoomPhase.COMPLETE;
                                        AbstractDungeon.gUnlockScreen.open(unlockBundle, true);
                                        ReflectionHacks.setPrivate(AbstractDungeon.dynamicBanner, DynamicBanner.class, "label", uiStrings.TEXT[0]);
                                        isDone = true;
                                    }
                                });
                                return SpireReturn.Return(null);
                            }
                            return SpireReturn.Return(null);
                        }
                    } else if ("ACCEPT".equals(screen.name()) && reversedPortal) {
                        AbstractDungeon.resetPlayer();
                        AbstractDungeon.player.movePosition(Settings.WIDTH * 0.25F, AbstractDungeon.floorY);
                        CardCrawlGame.nextDungeon = "Exordium";
                        AbstractDungeon.isDungeonBeaten = true;

                        CardCrawlGame.music.fadeOutBGM();
                        CardCrawlGame.music.fadeOutTempBGM();
                        AbstractDungeon.fadeOut();
                        AbstractDungeon.topLevelEffects.clear();
                        AbstractDungeon.actionManager.actions.clear();
                        AbstractDungeon.effectList.clear();
                        AbstractDungeon.effectsQueue.clear();
                        AbstractDungeon.getCurrRoom().phase = AbstractRoom.RoomPhase.COMPLETE;
                        AbstractDungeon.rs = AbstractDungeon.RenderScene.NORMAL;
                        GenericEventDialog.cleanUp();
                        AbstractDungeon.floorNum = 1;
                        AbstractDungeon.actNum = 0;
                        AbstractDungeon.id = Exordium.ID;
                        AbstractDungeon.player.masterDeck.removeCard(AscendersBane.ID);
                        if (Loader.isModLoaded("actlikeit")) {
                            try {
                                Class<?> cls = Class.forName("actlikeit.savefields.BehindTheScenesActNum");
                                Field field = cls.getDeclaredField("bc");
                                field.setAccessible(true);
                                Object bc = field.get(null);
                                field = cls.getDeclaredField("actNum");
                                field.setAccessible(true);
                                field.set(bc, 0);
                            } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
                                e.printStackTrace();
                            }
                        }
                        return SpireReturn.Return(null);
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
            return SpireReturn.Continue();
        }
    }

    static {
        eventStrings = CardCrawlGame.languagePack.getEventString(ID);
        NAME = eventStrings.NAME;
        DESCRIPTIONS = eventStrings.DESCRIPTIONS;
        OPTIONS = eventStrings.OPTIONS;
    }
}
